Micron Document
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
| SparkN0de-git | SparkN0de |
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

Node / ReticulumProjects / MeshChatX.git / files / meshchatx / src / backend / auto_propagation_manager.py

Displaying Raw • Download


meshchatx/src/backend/auto_propagation_manager.py ad35cc8bacba258d1b433a52de9bbc0f33172bb7 (ad35cc8b) Text, 9.41 KB

T8b949e# SPDX-License-Identifier: 0BSD

Tff7b72import T7ee787asyncio
Tff7b72import T7ee787contextlib
Tff7b72import T7ee787time

Tff7b72import T7ee787RNS
Tff7b72from T7ee787LXMFT7ee787.T7ee787LXMRouter Tff7b72import Te6edf3LXMRouter

Tff7b72from T7ee787meshchatxT7ee787.T7ee787srcT7ee787.T7ee787backendT7ee787.T7ee787async_utils Tff7b72import Te6edf3AsyncUtils
Tff7b72from T7ee787meshchatxT7ee787.T7ee787srcT7ee787.T7ee787backendT7ee787.T7ee787meshchat_utils Tff7b72import Te6edf3parse_lxmf_propagation_node_app_data
Tff7b72from T7ee787meshchatxT7ee787.T7ee787srcT7ee787.T7ee787backend Tff7b72import Te6edf3reticulum_pathfinding

Te6edf3_PROP_FAILURE_STATES Tff7b72= Tffa657frozensetTb4b4b4(
Tb4b4b4{
Te6edf3LXMRouterTff7b72.Td2a8ffPR_NO_PATHTb4b4b4,
Te6edf3LXMRouterTff7b72.Td2a8ffPR_LINK_FAILEDTb4b4b4,
Te6edf3LXMRouterTff7b72.Td2a8ffPR_TRANSFER_FAILEDTb4b4b4,
Te6edf3LXMRouterTff7b72.Td2a8ffPR_NO_IDENTITY_RCVDTb4b4b4,
Te6edf3LXMRouterTff7b72.Td2a8ffPR_NO_ACCESSTb4b4b4,
Te6edf3LXMRouterTff7b72.Td2a8ffPR_FAILEDTb4b4b4,
Te6edf3LXMRouterTff7b72.Td2a8ffPR_PATH_TIMEOUTTb4b4b4,
Tb4b4b4}Tb4b4b4,
Tb4b4b4)

Te6edf3PATH_WAIT_SECONDS Tff7b72= T79c0ff40.0
Te6edf3SYNC_PROBE_TIMEOUT_SECONDS Tff7b72= T79c0ff120.0
Te6edf3POLL_INTERVAL_SECONDS Tff7b72= T79c0ff0.2


Tff7b72class T56d364AutoPropagationManagerTb4b4b4:
Tff7b72def Tff7b72__init__Tb4b4b4(Tff7b72selfTb4b4b4, Te6edf3appTb4b4b4, Te6edf3contextTb4b4b4)Tb4b4b4:
Tff7b72selfTff7b72.Td2a8ffapp Tff7b72= Te6edf3app
Tff7b72selfTff7b72.Td2a8ffcontext Tff7b72= Te6edf3context
Tff7b72selfTff7b72.Td2a8ffconfig Tff7b72= Te6edf3contextTff7b72.Td2a8ffconfig
Tff7b72selfTff7b72.Td2a8ffdatabase Tff7b72= Te6edf3contextTff7b72.Td2a8ffdatabase
Tff7b72selfTff7b72.Td2a8ffrunning Tff7b72= Tff7b72False
Tff7b72selfTff7b72.Td2a8ff_last_check Tff7b72= T79c0ff0
Tff7b72selfTff7b72.Td2a8ff_check_interval Tff7b72= T79c0ff300 T8b949e# 5 minutes

Tff7b72def Td2a8ffstopTb4b4b4(Tff7b72selfTb4b4b4)Tb4b4b4:
Tff7b72selfTff7b72.Td2a8ffrunning Tff7b72= Tff7b72False

Tff7b72async Tff7b72def Td2a8ff_runTb4b4b4(Tff7b72selfTb4b4b4)Tb4b4b4:
T8b949e# Wait a bit after startup to allow discovers to come in
Tff7b72await Te6edf3asyncioTff7b72.Td2a8ffsleepTb4b4b4(T79c0ff10Tb4b4b4)
Tff7b72selfTff7b72.Td2a8ffrunning Tff7b72= Tff7b72True

Tff7b72while Tff7b72selfTff7b72.Td2a8ffrunning Tff7b72and Tff7b72selfTff7b72.Td2a8ffcontextTff7b72.Td2a8ffrunningTb4b4b4:
Tff7b72tryTb4b4b4:
Tff7b72if Tff7b72selfTff7b72.Td2a8ffconfigTff7b72.Td2a8fflxmf_preferred_propagation_node_auto_selectTff7b72.Td2a8ffgetTb4b4b4(Tb4b4b4)Tb4b4b4:
Tff7b72await Tff7b72selfTff7b72.Td2a8ffcheck_and_update_propagation_nodeTb4b4b4(Tb4b4b4)
Tff7b72except Te6edf3asyncioTff7b72.Td2a8ffCancelledErrorTb4b4b4:
Tff7b72break
Tff7b72except Tf85149Exception Tff7b72as Te6edf3eTb4b4b4:
Tffa657printTb4b4b4(
Ta5d6fffTa5d6ff"Ta5d6ffError in AutoPropagationManager for Tffd700{Tff7b72selfTff7b72.Td2a8ffcontextTff7b72.Td2a8ffidentity_hashTffd700}Ta5d6ff: Tffd700{Te6edf3eTffd700}Ta5d6ff"Tb4b4b4,
Tb4b4b4)

Tff7b72await Te6edf3asyncioTff7b72.Td2a8ffsleepTb4b4b4(Tff7b72selfTff7b72.Td2a8ff_check_intervalTb4b4b4)

Tff7b72async Tff7b72def Td2a8ff_wait_for_pathTb4b4b4(Tff7b72selfTb4b4b4, Te6edf3dest_hashTb4b4b4: Tffa657bytesTb4b4b4, Te6edf3timeoutTb4b4b4: Tffa657floatTb4b4b4) Tff7b72-Tff7b72> Tffa657boolTb4b4b4:
Te6edf3r Tff7b72= Tff7b72selfTff7b72.Td2a8ffappTff7b72.Td2a8ffreticulum Tff7b72if Tff7b72selfTff7b72.Td2a8ffapp Tff7b72and Tffa657hasattrTb4b4b4(Tff7b72selfTff7b72.Td2a8ffappTb4b4b4, Ta5d6ff"Ta5d6ffreticulumTa5d6ff"Tb4b4b4) Tff7b72else Tff7b72None
Tff7b72return Tff7b72await Te6edf3reticulum_pathfindingTff7b72.Td2a8ffwait_for_pathTb4b4b4(
Te6edf3rTb4b4b4,
Te6edf3dest_hashTb4b4b4,
Te6edf3timeoutTb4b4b4,
Te6edf3poll_intervalTff7b72=Te6edf3POLL_INTERVAL_SECONDSTb4b4b4,
Tb4b4b4)

Tff7b72async Tff7b72def Td2a8ff_probe_propagation_syncTb4b4b4(Tff7b72selfTb4b4b4, Te6edf3node_hexTb4b4b4: Tffa657strTb4b4b4) Tff7b72-Tff7b72> Tffa657boolTb4b4b4:
Te6edf3ctx Tff7b72= Tff7b72selfTff7b72.Td2a8ffcontext
Te6edf3router Tff7b72= Te6edf3ctxTff7b72.Td2a8ffmessage_router
Tff7b72if Tff7b72not Te6edf3routerTb4b4b4:
Tff7b72return Tff7b72False
Tff7b72tryTb4b4b4:
Te6edf3dest Tff7b72= Tffa657bytesTff7b72.Td2a8fffromhexTb4b4b4(Te6edf3node_hexTb4b4b4)
Tff7b72if Tffa657lenTb4b4b4(Te6edf3destTb4b4b4) Tff7b72!= Te6edf3RNSTff7b72.Td2a8ffIdentityTff7b72.Td2a8ffTRUNCATED_HASHLENGTH Tff7b72/Tff7b72/ T79c0ff8Tb4b4b4:
Tff7b72return Tff7b72False
Tff7b72except Tf85149ExceptionTb4b4b4:
Tff7b72return Tff7b72False

T8b949e# Ensure any previous sync is fully cancelled and state is idle
Tff7b72selfTff7b72.Td2a8ffappTff7b72.Td2a8ffstop_propagation_node_syncTb4b4b4(Te6edf3contextTff7b72=Te6edf3ctxTb4b4b4)
Te6edf3settle_deadline Tff7b72= Te6edf3timeTff7b72.Td2a8ffmonotonicTb4b4b4(Tb4b4b4) Tff7b72+ T79c0ff5.0
Tff7b72while Te6edf3timeTff7b72.Td2a8ffmonotonicTb4b4b4(Tb4b4b4) Tff7b72< Te6edf3settle_deadlineTb4b4b4:
Tff7b72if Te6edf3routerTff7b72.Td2a8ffpropagation_transfer_state Tff7b72== Te6edf3LXMRouterTff7b72.Td2a8ffPR_IDLETb4b4b4:
Tff7b72break
Tff7b72await Te6edf3asyncioTff7b72.Td2a8ffsleepTb4b4b4(Te6edf3POLL_INTERVAL_SECONDSTb4b4b4)
Tff7b72elseTb4b4b4:
Tff7b72with Te6edf3contextlibTff7b72.Td2a8ffsuppressTb4b4b4(Tf85149ExceptionTb4b4b4)Tb4b4b4:
Te6edf3routerTff7b72.Td2a8ffpropagation_transfer_state Tff7b72= Te6edf3LXMRouterTff7b72.Td2a8ffPR_IDLE

Tff7b72tryTb4b4b4:
Te6edf3routerTff7b72.Td2a8ffset_outbound_propagation_nodeTb4b4b4(Te6edf3destTb4b4b4)
Tff7b72except Tf85149ExceptionTb4b4b4:
Tff7b72return Tff7b72False

Te6edf3routerTff7b72.Td2a8ffrequest_messages_from_propagation_nodeTb4b4b4(Te6edf3ctxTff7b72.Td2a8ffidentityTb4b4b4)

Te6edf3deadline Tff7b72= Te6edf3timeTff7b72.Td2a8ffmonotonicTb4b4b4(Tb4b4b4) Tff7b72+ Te6edf3SYNC_PROBE_TIMEOUT_SECONDS

T8b949e# Wait for the sync to actually start (leave idle)
Tff7b72while Te6edf3timeTff7b72.Td2a8ffmonotonicTb4b4b4(Tb4b4b4) Tff7b72< Te6edf3deadlineTb4b4b4:
Te6edf3state Tff7b72= Te6edf3routerTff7b72.Td2a8ffpropagation_transfer_state
Tff7b72if Te6edf3state Tff7b72in Te6edf3_PROP_FAILURE_STATESTb4b4b4:
Tff7b72selfTff7b72.Td2a8ffappTff7b72.Td2a8ffstop_propagation_node_syncTb4b4b4(Te6edf3contextTff7b72=Te6edf3ctxTb4b4b4)
Tff7b72return Tff7b72False
Tff7b72if Te6edf3state Tff7b72!= Te6edf3LXMRouterTff7b72.Td2a8ffPR_IDLETb4b4b4:
Tff7b72break
Tff7b72await Te6edf3asyncioTff7b72.Td2a8ffsleepTb4b4b4(Te6edf3POLL_INTERVAL_SECONDSTb4b4b4)
Tff7b72elseTb4b4b4:
T8b949e# Never left idle -> failed to start
Tff7b72selfTff7b72.Td2a8ffappTff7b72.Td2a8ffstop_propagation_node_syncTb4b4b4(Te6edf3contextTff7b72=Te6edf3ctxTb4b4b4)
Tff7b72return Tff7b72False

T8b949e# Wait for the sync to finish (return to idle)
Tff7b72while Te6edf3timeTff7b72.Td2a8ffmonotonicTb4b4b4(Tb4b4b4) Tff7b72< Te6edf3deadlineTb4b4b4:
Te6edf3state Tff7b72= Te6edf3routerTff7b72.Td2a8ffpropagation_transfer_state
Tff7b72if Te6edf3state Tff7b72in Te6edf3_PROP_FAILURE_STATESTb4b4b4:
Tff7b72selfTff7b72.Td2a8ffappTff7b72.Td2a8ffstop_propagation_node_syncTb4b4b4(Te6edf3contextTff7b72=Te6edf3ctxTb4b4b4)
Tff7b72return Tff7b72False
Tff7b72if Te6edf3state Tff7b72== Te6edf3LXMRouterTff7b72.Td2a8ffPR_IDLETb4b4b4:
T8b949e# Success: we left idle and now we're back
Tff7b72selfTff7b72.Td2a8ffappTff7b72.Td2a8ffstop_propagation_node_syncTb4b4b4(Te6edf3contextTff7b72=Te6edf3ctxTb4b4b4)
Tff7b72return Tff7b72True
Tff7b72await Te6edf3asyncioTff7b72.Td2a8ffsleepTb4b4b4(Te6edf3POLL_INTERVAL_SECONDSTb4b4b4)

Tff7b72selfTff7b72.Td2a8ffappTff7b72.Td2a8ffstop_propagation_node_syncTb4b4b4(Te6edf3contextTff7b72=Te6edf3ctxTb4b4b4)
Tff7b72return Tff7b72False

Tff7b72async Tff7b72def Td2a8ffcheck_and_update_propagation_nodeTb4b4b4(Tff7b72selfTb4b4b4)Tb4b4b4:
Te6edf3ctx Tff7b72= Tff7b72selfTff7b72.Td2a8ffcontext
Te6edf3router Tff7b72= Te6edf3ctxTff7b72.Td2a8ffmessage_router
Tff7b72if Tff7b72not Te6edf3routerTb4b4b4:
Tff7b72return

Te6edf3previous_hex Tff7b72= Tb4b4b4(
Tff7b72selfTff7b72.Td2a8ffconfigTff7b72.Td2a8fflxmf_preferred_propagation_node_destination_hashTff7b72.Td2a8ffgetTb4b4b4(Tb4b4b4)
Tb4b4b4)

T8b949e# If a sync is in progress, only interrupt it when the current node
T8b949e# appears unreachable or the path is stale/unresponsive. This prevents
T8b949e# getting stuck on a node we cannot actually reach.
Tff7b72if Te6edf3routerTff7b72.Td2a8ffpropagation_transfer_state Tff7b72!= Te6edf3LXMRouterTff7b72.Td2a8ffPR_IDLETb4b4b4:
Te6edf3current_path_ok Tff7b72= Tff7b72False
Tff7b72if Te6edf3previous_hexTb4b4b4:
Tff7b72tryTb4b4b4:
Te6edf3current_dest Tff7b72= Tffa657bytesTff7b72.Td2a8fffromhexTb4b4b4(Te6edf3previous_hexTb4b4b4)
Te6edf3current_has_path Tff7b72= Te6edf3RNSTff7b72.Td2a8ffTransportTff7b72.Td2a8ffhas_pathTb4b4b4(Te6edf3current_destTb4b4b4)
Te6edf3current_path_ok Tff7b72= Tb4b4b4(
Te6edf3current_has_path
Tff7b72and Tff7b72not Te6edf3RNSTff7b72.Td2a8ffTransportTff7b72.Td2a8ffpath_is_unresponsiveTb4b4b4(Te6edf3current_destTb4b4b4)
Tff7b72and Tff7b72not Te6edf3reticulum_pathfindingTff7b72.Td2a8fftransport_path_table_entry_is_expiredTb4b4b4(
Te6edf3current_destTb4b4b4,
Tb4b4b4)
Tb4b4b4)
Tff7b72except Tf85149ExceptionTb4b4b4:
Tff7b72pass
Tff7b72if Te6edf3current_path_okTb4b4b4:
T8b949e# Sync is likely making progress – let it finish.
Tff7b72return
T8b949e# Current node is unreachable – stop the stuck sync so we can
T8b949e# look for a working alternative.
Tff7b72selfTff7b72.Td2a8ffappTff7b72.Td2a8ffstop_propagation_node_syncTb4b4b4(Te6edf3contextTff7b72=Te6edf3ctxTb4b4b4)
T8b949e# Wait briefly for the router to settle back to idle before we
T8b949e# start probing other nodes.
Te6edf3settle_deadline Tff7b72= Te6edf3timeTff7b72.Td2a8ffmonotonicTb4b4b4(Tb4b4b4) Tff7b72+ T79c0ff5.0
Tff7b72while Te6edf3timeTff7b72.Td2a8ffmonotonicTb4b4b4(Tb4b4b4) Tff7b72< Te6edf3settle_deadlineTb4b4b4:
Tff7b72if Te6edf3routerTff7b72.Td2a8ffpropagation_transfer_state Tff7b72== Te6edf3LXMRouterTff7b72.Td2a8ffPR_IDLETb4b4b4:
Tff7b72break
Tff7b72await Te6edf3asyncioTff7b72.Td2a8ffsleepTb4b4b4(Te6edf3POLL_INTERVAL_SECONDSTb4b4b4)
Tff7b72elseTb4b4b4:
Tff7b72with Te6edf3contextlibTff7b72.Td2a8ffsuppressTb4b4b4(Tf85149ExceptionTb4b4b4)Tb4b4b4:
Te6edf3routerTff7b72.Td2a8ffpropagation_transfer_state Tff7b72= Te6edf3LXMRouterTff7b72.Td2a8ffPR_IDLE

Te6edf3announces Tff7b72= Tff7b72selfTff7b72.Td2a8ffdatabaseTff7b72.Td2a8ffannouncesTff7b72.Td2a8ffget_announcesTb4b4b4(Te6edf3aspectTff7b72=Ta5d6ff"Ta5d6fflxmf.propagationTa5d6ff"Tb4b4b4)

Te6edf3best_by_hexTb4b4b4: Tffa657dictTb4b4b4[Tffa657strTb4b4b4, Tffa657tupleTb4b4b4[Tffa657intTb4b4b4, Tffa657strTb4b4b4]Tb4b4b4] Tff7b72= Tb4b4b4{Tb4b4b4}
Tff7b72for Te6edf3announce Tff7b72in Te6edf3announcesTb4b4b4:
Te6edf3dest_hex Tff7b72= Te6edf3announceTb4b4b4[Ta5d6ff"Ta5d6ffdestination_hashTa5d6ff"Tb4b4b4]
Te6edf3node_data Tff7b72= Te6edf3parse_lxmf_propagation_node_app_dataTb4b4b4(Te6edf3announceTb4b4b4[Ta5d6ff"Ta5d6ffapp_dataTa5d6ff"Tb4b4b4]Tb4b4b4)
Tff7b72if Tff7b72not Te6edf3node_data Tff7b72or Tff7b72not Te6edf3node_dataTff7b72.Td2a8ffgetTb4b4b4(Ta5d6ff"Ta5d6ffenabledTa5d6ff"Tb4b4b4, Tff7b72FalseTb4b4b4)Tb4b4b4:
Tff7b72continue
Tff7b72tryTb4b4b4:
Te6edf3dest_hash Tff7b72= Tffa657bytesTff7b72.Td2a8fffromhexTb4b4b4(Te6edf3dest_hexTb4b4b4)
Tff7b72except Tf85149ValueErrorTb4b4b4:
Tff7b72continue
Tff7b72if Te6edf3RNSTff7b72.Td2a8ffTransportTff7b72.Td2a8ffhas_pathTb4b4b4(Te6edf3dest_hashTb4b4b4)Tb4b4b4:
Te6edf3hops Tff7b72= Te6edf3RNSTff7b72.Td2a8ffTransportTff7b72.Td2a8ffhops_toTb4b4b4(Te6edf3dest_hashTb4b4b4)
Tff7b72elseTb4b4b4:
Te6edf3hops Tff7b72= T79c0ff10Tff7b72*Tff7b72*T79c0ff9
Te6edf3prev Tff7b72= Te6edf3best_by_hexTff7b72.Td2a8ffgetTb4b4b4(Te6edf3dest_hexTb4b4b4)
Tff7b72if Te6edf3prev Tff7b72is Tff7b72None Tff7b72or Te6edf3hops Tff7b72< Te6edf3prevTb4b4b4[T79c0ff0Tb4b4b4]Tb4b4b4:
Te6edf3best_by_hexTb4b4b4[Te6edf3dest_hexTb4b4b4] Tff7b72= Tb4b4b4(Te6edf3hopsTb4b4b4, Te6edf3dest_hexTb4b4b4)

Te6edf3sorted_candidates Tff7b72= Tffa657sortedTb4b4b4(Te6edf3best_by_hexTff7b72.Td2a8ffvaluesTb4b4b4(Tb4b4b4)Tb4b4b4, Te6edf3keyTff7b72=Tff7b72lambda Te6edf3xTb4b4b4: Te6edf3xTb4b4b4[T79c0ff0Tb4b4b4]Tb4b4b4)
Tff7b72if Tff7b72not Te6edf3sorted_candidatesTb4b4b4:
Tff7b72return

Te6edf3orderedTb4b4b4: Tffa657listTb4b4b4[Tffa657tupleTb4b4b4[Tffa657intTb4b4b4, Tffa657strTb4b4b4]Tb4b4b4] Tff7b72= Tb4b4b4[Tb4b4b4]
Te6edf3seen_hexTb4b4b4: Tffa657setTb4b4b4[Tffa657strTb4b4b4] Tff7b72= Tffa657setTb4b4b4(Tb4b4b4)
Tff7b72if Te6edf3previous_hex Tff7b72and Te6edf3previous_hex Tff7b72in Te6edf3best_by_hexTb4b4b4:
Te6edf3orderedTff7b72.Td2a8ffappendTb4b4b4(Te6edf3best_by_hexTb4b4b4[Te6edf3previous_hexTb4b4b4]Tb4b4b4)
Te6edf3seen_hexTff7b72.Td2a8ffaddTb4b4b4(Te6edf3previous_hexTb4b4b4)
Tff7b72for Te6edf3item Tff7b72in Te6edf3sorted_candidatesTb4b4b4:
Tff7b72if Te6edf3itemTb4b4b4[T79c0ff1Tb4b4b4] Tff7b72not Tff7b72in Te6edf3seen_hexTb4b4b4:
Te6edf3orderedTff7b72.Td2a8ffappendTb4b4b4(Te6edf3itemTb4b4b4)
Te6edf3seen_hexTff7b72.Td2a8ffaddTb4b4b4(Te6edf3itemTb4b4b4[T79c0ff1Tb4b4b4]Tb4b4b4)

Tff7b72for Te6edf3_hopsTb4b4b4, Te6edf3node_hex Tff7b72in Te6edf3orderedTb4b4b4:
Tff7b72tryTb4b4b4:
Te6edf3dest_hash Tff7b72= Tffa657bytesTff7b72.Td2a8fffromhexTb4b4b4(Te6edf3node_hexTb4b4b4)
Tff7b72except Tf85149ValueErrorTb4b4b4:
Tff7b72continue

Tff7b72if Tff7b72not Tff7b72await Tff7b72selfTff7b72.Td2a8ff_wait_for_pathTb4b4b4(Te6edf3dest_hashTb4b4b4, Te6edf3PATH_WAIT_SECONDSTb4b4b4)Tb4b4b4:
Tff7b72continue

Tff7b72if Tff7b72not Tff7b72await Tff7b72selfTff7b72.Td2a8ff_probe_propagation_syncTb4b4b4(Te6edf3node_hexTb4b4b4)Tb4b4b4:
Tff7b72continue

Tff7b72if Te6edf3node_hex Tff7b72!= Te6edf3previous_hexTb4b4b4:
Tffa657printTb4b4b4(
Ta5d6fffTa5d6ff"Ta5d6ffAuto-propagation: Switching to verified node Tffd700{Te6edf3node_hexTffd700}Ta5d6ff Ta5d6ff"
Ta5d6fffTa5d6ff"Ta5d6fffor Tffd700{Tff7b72selfTff7b72.Td2a8ffcontextTff7b72.Td2a8ffidentity_hashTffd700}Ta5d6ff"Tb4b4b4,
Tb4b4b4)
Tff7b72selfTff7b72.Td2a8ffappTff7b72.Td2a8ffset_active_propagation_nodeTb4b4b4(Te6edf3node_hexTb4b4b4, Te6edf3contextTff7b72=Tff7b72selfTff7b72.Td2a8ffcontextTb4b4b4)
Tff7b72selfTff7b72.Td2a8ffconfigTff7b72.Td2a8fflxmf_preferred_propagation_node_destination_hashTff7b72.Td2a8ffsetTb4b4b4(
Te6edf3node_hexTb4b4b4,
Tb4b4b4)
Te6edf3AsyncUtilsTff7b72.Td2a8ffrun_asyncTb4b4b4(
Tff7b72selfTff7b72.Td2a8ffappTff7b72.Td2a8ffsend_config_to_websocket_clientsTb4b4b4(Te6edf3contextTff7b72=Te6edf3ctxTb4b4b4)Tb4b4b4,
Tb4b4b4)
Tff7b72return

T8b949e# None of the candidates worked. If the previously-selected node is
T8b949e# still unreachable, clear it rather than restoring a broken node.
Tff7b72if Te6edf3previous_hexTb4b4b4:
Tff7b72tryTb4b4b4:
Te6edf3previous_dest Tff7b72= Tffa657bytesTff7b72.Td2a8fffromhexTb4b4b4(Te6edf3previous_hexTb4b4b4)
Tff7b72if Te6edf3RNSTff7b72.Td2a8ffTransportTff7b72.Td2a8ffhas_pathTb4b4b4(Te6edf3previous_destTb4b4b4)Tb4b4b4:
Tff7b72selfTff7b72.Td2a8ffappTff7b72.Td2a8ffset_active_propagation_nodeTb4b4b4(
Te6edf3previous_hexTb4b4b4, Te6edf3contextTff7b72=Tff7b72selfTff7b72.Td2a8ffcontext
Tb4b4b4)
Tff7b72return
Tff7b72except Tf85149ExceptionTb4b4b4:
Tff7b72pass
Tff7b72selfTff7b72.Td2a8ffappTff7b72.Td2a8ffremove_active_propagation_nodeTb4b4b4(Te6edf3contextTff7b72=Tff7b72selfTff7b72.Td2a8ffcontextTb4b4b4)
Tff7b72elseTb4b4b4:
Tff7b72selfTff7b72.Td2a8ffappTff7b72.Td2a8ffremove_active_propagation_nodeTb4b4b4(Te6edf3contextTff7b72=Tff7b72selfTff7b72.Td2a8ffcontextTb4b4b4)


──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────